package xin.yangshuai.basic01.download;


import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.UUID;

/**
 * DownloadUtils
 *
 * @author shuai
 * @date 2020/10/27
 */
public class DownloadUtils1 {

    private static final Logger log = LoggerFactory.getLogger(DownloadUtils1.class);

    private static final String IE_USER_AGENT = "msie";
    private static final String IE_BROWSER = "IE";

    private static final String EDGE_USER_AGENT = "edge";
    private static final String EDGE_BROWSER = "EDGE";

    private static final String OPERA_USER_AGENT = "opera";
    private static final String OPERA_BROWSER = "OPERA";

    private static final String SAFARI_USER_AGENT = "safari";
    private static final String SAFARI_BROWSER = "SAFARI";

    private static final String CHROME_USER_AGENT = "applewebkit";
    private static final String CHROME_BROWSER = "CHROME";

    private static final String FIREFOX_USER_AGENT = "mozilla";
    private static final String FIREFOX_BROWSER = "FIREFOX";


    private static String attachmentFilename = "attachment;fileName{0}";

    /**
     * 获取原始文件名，新文件名，文件后缀
     *
     * @param fileUrl
     * @return
     */
    public static String[] urlFileInfo(String fileUrl) {

        int index = fileUrl.lastIndexOf("/");

        String oldFilename = fileUrl.substring(index + 1);

        index = oldFilename.lastIndexOf(".");
        String oldFilenameOnly = oldFilename.substring(0, index);
        // 文件后缀
        String fileSuffix = oldFilename.substring(index + 1);

        UUID obj = UUID.randomUUID();
        String newFilenameOnly = String.valueOf(obj).replace("-", "");

        return new String[]{oldFilenameOnly, newFilenameOnly, fileSuffix};
    }

    /**
     * 显示（图片，pdf，视频）或下载文件
     *
     * @param fileUrl  文件路径
     * @param filename 文件名
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public static void receive(String fileUrl, String filename, HttpServletRequest request, HttpServletResponse response) throws Exception {

        URL url = new URL(fileUrl);
        URLConnection urlConnection = url.openConnection();
        // http的连接类
        HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
        // 设置超时
        httpURLConnection.setConnectTimeout(1000 * 5);
        // 设置请求方式，默认是GET
        httpURLConnection.setRequestMethod("GET");
        // 设置字符编码
        httpURLConnection.setRequestProperty("Charset", "UTF-8");
        // 打开连接
        httpURLConnection.connect();


        byte[] buffer = new byte[1024];


        String[] urlFileInfo = urlFileInfo(fileUrl);

        //如果存在文件名，并且文件名不为空，则下载并且使用文件名
        if (StringUtils.isNotBlank(filename)) {
            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition", getAttachmentFilename(request, filename));
        } else {
            //如果不存在文件名，如果是图片，pdf可以在浏览器显示
            String fileType = urlFileInfo[2].toLowerCase();
            //设置文件ContentType类型
            if ("jpg,jepg,gif,png".contains(fileType)) {
                //图片类型
                response.setContentType("image/" + fileType);
            } else if ("pdf".contains(fileType)) {
                //pdf类型
                response.setContentType("application/pdf");
            } else {
                //其它强制下载
                response.setContentType("application/force-download");
                String oldFilename = urlFileInfo[0];
                response.addHeader("Content-Disposition", getAttachmentFilename(request, oldFilename));
            }
        }

        BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());
        OutputStream outputStream = response.getOutputStream();
        int len;
        while ((len = bis.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }
    }


    /**
     * 获取attachmentFilename
     *
     * @param request
     * @param filename
     * @return
     * @throws Exception
     */
    private static String getAttachmentFilename(HttpServletRequest request, String filename) throws Exception {

        String browser = getBrowser(request);
        String newFilename = URLEncoder.encode(filename, "UTF-8");

        String attachmentFilenameURLEncoder = MessageFormat.format(attachmentFilename, "=" + newFilename);
        String attachmentFilenameUTF8 = MessageFormat.format(attachmentFilename, "*=UTF-8''" + newFilename);
        String attachmentFilenameISO = MessageFormat.format(attachmentFilename, "=" + new String(filename.getBytes("UTF-8"), "iso-8859-1"));
//        String attachmentFilenameMimeUtility = MessageFormat.format(attachmentFilename, "=" + MimeUtility.encodeText(filename, "UTF8", "B"));

        switch (browser) {
            case EDGE_BROWSER:
                // edge浏览器
                return attachmentFilenameURLEncoder;
            case IE_BROWSER:
                // IE浏览器，只能采用URLEncoder编码（只适用于IE11以下,因为在IE11中UserAgent不再包含MSIE字符串）
                return attachmentFilenameURLEncoder;
            case OPERA_BROWSER:
                // Opera浏览器只能采用filename*
                return attachmentFilenameUTF8;
            case SAFARI_BROWSER:
                // Safari浏览器，只能采用ISO编码的中文输出（苹果的）
                return attachmentFilenameISO;
//            case CHROME_BROWSER:
//                // Chrome浏览器，只能采用MimeUtility编码或ISO编码的中文输出
//                // 实际上，这段代码不会走，因为到目前为止，谷歌浏览器的userAgent中存在safari。但因为谷歌浏览器兼容safari，所以，谷歌浏览器也好使
//                return attachmentFilenameMimeUtility;
            case FIREFOX_BROWSER:
                // FireFox浏览器，可以使用MimeUtility或filename*或ISO编码的中文输出
                // IE11和FireFox会走这个
                // 1. 之所以会使用mozilla判断，而不是FireFox，是因为Mozilla一般浏览器都有，可以作为默认的；二来FireFox前身是mozilla，所以FireFox中的userAgent自带mozilla参数。
                // 2. IE11中的userAgent去掉了MSIE。可以认为IE11开始，逐渐向标准化靠拢。
                return attachmentFilenameUTF8;
            default:
                return attachmentFilenameURLEncoder;
        }
    }

    /**
     * 获取浏览器类型
     *
     * @param request
     * @return
     */
    private static String getBrowser(HttpServletRequest request) {
        String userAgent = request.getHeader("USER-AGENT");
        if (userAgent != null) {
            userAgent = userAgent.toLowerCase();
            if (userAgent.indexOf(EDGE_USER_AGENT) != -1) {
                log.info("当前浏览器是edge");
                return EDGE_BROWSER;
            }
            if (userAgent.indexOf(IE_USER_AGENT) != -1) {
                log.info("当前浏览器是ie11以下");
                return IE_BROWSER;
            }
            if (userAgent.indexOf(OPERA_USER_AGENT) != -1) {
                log.info("当前浏览器是opera");
                return OPERA_BROWSER;
            }
            if (userAgent.indexOf(SAFARI_USER_AGENT) != -1) {
                log.info("当前浏览器是safari或者chrome");
                return SAFARI_BROWSER;
            }
            if (userAgent.indexOf(CHROME_USER_AGENT) != -1) {
                log.info("当前浏览器是chrome");
                return CHROME_BROWSER;
            }
            if (userAgent.indexOf(FIREFOX_USER_AGENT) != -1) {
                log.info("当前浏览器是firefox或者ie11");
                return FIREFOX_BROWSER;
            }
        }
        return null;
    }
}